package com.crm.business.crm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.crm.business.admin.service.AdminFileService;
import com.crm.business.admin.service.AdminService;
import com.crm.business.crm.mapper.CrmReceivablesDataMapper;
import com.crm.business.crm.mapper.CrmRefundMapper;
import com.crm.business.crm.service.*;
import com.crm.business.examine.service.ExamineService;
import com.crm.common.crm.common.ElasticUtil;
import com.crm.common.crm.constant.*;
import com.crm.common.crm.entity.BO.*;
import com.crm.common.exception.CustomException;
import com.crm.common.ka.core.feign.admin.entity.AdminConfigBo;
import com.crm.business.utils.ActionRecordUtil;
import com.crm.common.crm.common.CrmModel;
import com.crm.common.crm.entity.PO.*;
import com.crm.common.crm.entity.VO.CrmFieldSortVO;
import com.crm.common.crm.entity.VO.CrmInfoNumVO;
import com.crm.common.crm.entity.VO.CrmModelFiledVO;
import com.crm.common.ka.core.common.Const;
import com.crm.common.ka.core.entity.BasePage;
import com.crm.common.ka.core.exception.CrmException;
import com.crm.common.ka.core.feign.admin.entity.AdminMessage;
import com.crm.common.ka.core.feign.admin.entity.AdminMessageEnum;
import com.crm.common.ka.core.feign.examine.entity.ExamineRecordReturnVO;
import com.crm.common.ka.core.feign.examine.entity.ExamineRecordSaveBO;
import com.crm.business.servlet.ApplicationContextHolder;
import com.crm.business.servlet.BaseServiceImpl;
import com.crm.common.ka.core.servlet.upload.FileEntity;
import com.crm.business.utils.UserCacheUtil;
import com.crm.business.utils.UserUtil;
import com.crm.common.utils.DateUtils;
import com.crm.common.utils.StringUtils;
import com.crm.common.utils.spring.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.metrics.sum.ParsedSum;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 回款表 服务实现类
 * </p>
 *
 * @author zhangzhiwei
 * @since 2020-05-28
 */
@Service
@Slf4j
public class CrmReFundServiceImpl extends BaseServiceImpl<CrmRefundMapper, CrmRefund> implements ICrmReFundService, CrmPageService {

    @Autowired
    private ICrmFieldService crmFieldService;

    @Autowired
    private ICrmReceivablesDataService crmReceivablesDataService;

    @Autowired
    private ICrmReceivablesService crmReceivablesService;

    @Autowired
    private ICrmContractService crmContractService;

    @Autowired
    private ICrmExamineService crmExamineService;

    @Autowired
    private ICrmExamineRecordService examineRecordService;

    @Autowired
    private AdminService adminService;

    @Autowired
    private ICrmNumberSettingService crmNumberSettingService;

    @Autowired
    private ICrmActivityService crmActivityService;

    @Autowired
    private ICrmReceivablesPlanService crmReceivablesPlanService;

    @Autowired
    private ICrmActionRecordService crmActionRecordService;

    @Autowired
    private ICrmCustomerService crmCustomerService;

    @Autowired
    private ICrmStudentService crmStudentService;

    @Autowired
    private ICrmLeadsService crmLeadsService;

    @Autowired
    private ActionRecordUtil actionRecordUtil;

    @Autowired
    private AdminFileService adminFileService;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ExamineService examineService;

    @Autowired
    private ICrmRefundDataService crmRefundDataService;


    /**
     * 大的搜索框的搜索字段
     *
     * @return fields
     */
    @Override
    public String[] appendSearch() {
        return new String[]{"number", "customerName", "studentName"};
    }

    @Override
    public CrmEnum getLabel() {
        return CrmEnum.REFUND;
    }

    //回款更新ROI数据判断
    public static boolean IS_DELETE = true;

    /**
     * 查询所有字段
     *
     * @return data
     */
    @Override
    public List<CrmModelFiledVO> queryDefaultField() {
        List<CrmModelFiledVO> filedList = crmFieldService.queryField(getLabel().getType());
//        filedList.add(new CrmModelFiledVO("lastTime", FieldEnum.DATETIME, 1));
        filedList.add(new CrmModelFiledVO("updateTime", FieldEnum.DATETIME, 1));
        filedList.add(new CrmModelFiledVO("createTime", FieldEnum.DATETIME, 1));
        filedList.add(new CrmModelFiledVO("ownerUserId", FieldEnum.USER, 1));
        filedList.add(new CrmModelFiledVO("createUserId", FieldEnum.USER, 1));
        filedList.add(new CrmModelFiledVO("ownerDeptId", FieldEnum.STRUCTURE, 1));
        filedList.add(new CrmModelFiledVO("checkStatus", FieldEnum.TEXT, 1));
        filedList.add(new CrmModelFiledVO("ownerDeptName", FieldEnum.TEXT, 1));
        filedList.add(new CrmModelFiledVO("courseSource", FieldEnum.TEXT, 1));
        //filedList.add(new CrmModelFiledVO("salesUserId", FieldEnum.USER,1));
        return filedList;
    }

    /**
     * 查询字段配置
     *
     * @param id 主键ID
     * @return data
     */
    @Override
    public List<CrmModelFiledVO> queryField(Integer id) {
        CrmModel crmModel = queryById(id);
        if (id != null){
//            List<JSONObject> customerList = new ArrayList<>();
//            JSONObject customer = new JSONObject();
//            customerList.add(customer.fluentPut("customerId", crmModel.get("customerId")).fluentPut("customerName", crmModel.get("customerName")));
//            crmModel.put("customerId", customerList);

            List<JSONObject> studentList = new ArrayList<>();
            JSONObject student = new JSONObject();
            studentList.add(student.fluentPut("studentId", crmModel.get("studentId")).fluentPut("studentName", crmModel.get("studentName")));
            crmModel.put("studentId", studentList);

            crmModel.put("contractId", Collections.singletonList(new JSONObject().fluentPut("contractId",crmModel.get("contractId")).fluentPut("contractNum",crmModel.get("contractNum"))));
            crmModel.put("receivablesId", Collections.singletonList(new JSONObject().fluentPut("receivablesId",crmModel.get("receivablesId")).fluentPut("receivablesNumber",crmModel.get("receivablesNumber"))));

        }
        List<CrmModelFiledVO> vos = crmFieldService.queryField(crmModel);

        vos.removeIf(field -> field.getFieldName().equals("number"));

        vos.removeIf(field -> field.getFieldName().equals("source"));

        vos.removeIf(field -> field.getFieldName().equals("bankCardAddr"));

        vos.removeIf(field -> field.getFieldName().equals("dataFrom"));
        vos.removeIf(field -> field.getFieldName().equals("customerSource"));
        vos.removeIf(field -> field.getFieldName().equals("ownerDeptId"));
        vos.removeIf(field -> field.getFieldName().equals("isRepetition"));
        vos.removeIf(field -> field.getFieldName().equals("courseSource"));
        //去除大类
        vos.removeIf(field -> field.getFieldName().equals("categories"));
        //去除销售类型
        vos.removeIf(field -> field.getFieldName().equals("salesType"));
        // 去除逾期状态
        vos.removeIf(field -> field.getFieldName().equals("overdueStatus"));
        // 去除退款日期
        vos.removeIf(field -> field.getFieldName().equals("refundDate"));
        // 退款类型
        vos.removeIf(field -> field.getFieldName().equals("refundCategory"));
        // 合同类别
        vos.removeIf(field -> field.getFieldName().equals("contractCategory"));
        // 补款金额
        vos.removeIf(field -> field.getFieldName().equals("billMoney"));

        JSONObject value = new JSONObject();
        value.put("bankCardAddr", crmModel.get("bankCardAddr"));
        if (crmModel.get("bankCardAddr") != null) {
            LinkedHashMap addressVal = JSON.parseObject(crmModel.get("bankCardAddr").toString(), LinkedHashMap.class);
            vos.add(4, new CrmModelFiledVO("map_bankCardAddr", FieldEnum.ADDRESS, "开户行所在省市区", 1).setIsNull(1).setValue(addressVal).setAuthLevel(3));
        } else {
            LinkedHashMap addressVal = null;
            vos.add(4, new CrmModelFiledVO("map_bankCardAddr", FieldEnum.ADDRESS, "开户行所在省市区", 1).setIsNull(1).setValue(addressVal).setAuthLevel(3));
        }

        String refundType = String.valueOf(crmModel.get("refundType"));
        vos.stream().forEach(crmModelFiledVO -> {
            if("原路退回".equals(refundType)){
                if("bankCardMsg".equals(crmModelFiledVO.getFieldName())
                        || "mapBankcardaddr".equals(crmModelFiledVO.getFieldName())
                        || "bankCardNumber".equals(crmModelFiledVO.getFieldName())
                        || "accountHolder".equals(crmModelFiledVO.getFieldName())){
                    crmModelFiledVO.setIsNull(0);
                }
            }
        });

        return vos;
    }

    /**
     * 查询字段配置
     *
     * @param id 主键ID
     * @return data
     */
    @Override
    public List<CrmModelFiledVO> queryCheckOkEditField(Integer id) {
        CrmModel crmModel = queryById(id);
        if (id != null){
            List<JSONObject> studentList = new ArrayList<>();
            JSONObject student = new JSONObject();
            studentList.add(student.fluentPut("studentId", crmModel.get("studentId")).fluentPut("studentName", crmModel.get("studentName")));
            crmModel.put("studentId", studentList);

            crmModel.put("contractId", Collections.singletonList(new JSONObject().fluentPut("contractId",crmModel.get("contractId")).fluentPut("contractNum",crmModel.get("contractNum"))));
            crmModel.put("receivablesId", Collections.singletonList(new JSONObject().fluentPut("receivablesId",crmModel.get("receivablesId")).fluentPut("receivablesNumber",crmModel.get("receivablesNumber"))));

        }
        List<CrmModelFiledVO> vos = crmFieldService.queryField(crmModel);

        Optional<CrmModelFiledVO> bankCardAddr = vos.stream().filter(field -> field.getFieldName().equals("bankCardAddr")).findFirst();
        Integer checkOkEdit = 0;
        if(bankCardAddr.isPresent()){
            checkOkEdit = bankCardAddr.get().getCheckOkEdit();
        }

        vos.removeIf(field -> field.getFieldName().equals("number"));
        vos.removeIf(field -> field.getFieldName().equals("source"));
        vos.removeIf(field -> field.getFieldName().equals("bankCardAddr"));
        vos.removeIf(field -> field.getFieldName().equals("dataFrom"));
        vos.removeIf(field -> field.getFieldName().equals("customerSource"));
        vos.removeIf(field -> field.getFieldName().equals("ownerDeptId"));
        vos.removeIf(field -> field.getFieldName().equals("isRepetition"));
        vos.removeIf(field -> field.getFieldName().equals("courseSource"));
        // 去除退款日期
        vos.removeIf(field -> field.getFieldName().equals("refundDate"));
        // 退款类型
        vos.removeIf(field -> field.getFieldName().equals("refundCategory"));
        // 合同类别
        vos.removeIf(field -> field.getFieldName().equals("contractCategory"));
        // 补款金额
        vos.removeIf(field -> field.getFieldName().equals("billMoney"));

        JSONObject value = new JSONObject();
        value.put("bankCardAddr", crmModel.get("bankCardAddr"));
        if (crmModel.get("bankCardAddr") != null) {
            LinkedHashMap addressVal = JSON.parseObject(crmModel.get("bankCardAddr").toString(), LinkedHashMap.class);
            vos.add(4, new CrmModelFiledVO("map_bankCardAddr", FieldEnum.ADDRESS, "开户行所在省市区", 1).setIsNull(1).setValue(addressVal).setAuthLevel(3).setCheckOkEdit(checkOkEdit));
        } else {
            LinkedHashMap addressVal = null;
            vos.add(4, new CrmModelFiledVO("map_bankCardAddr", FieldEnum.ADDRESS, "开户行所在省市区", 1).setIsNull(1).setValue(addressVal).setAuthLevel(3).setCheckOkEdit(checkOkEdit));
        }

        String refundType = String.valueOf(crmModel.get("refundType"));
        vos.stream().forEach(crmModelFiledVO -> {
            if("原路退回".equals(refundType)){
                if("bankCardMsg".equals(crmModelFiledVO.getFieldName())
                        || "mapBankcardaddr".equals(crmModelFiledVO.getFieldName())
                        || "bankCardNumber".equals(crmModelFiledVO.getFieldName())
                        || "accountHolder".equals(crmModelFiledVO.getFieldName())){
                    crmModelFiledVO.setIsNull(0);
                }
            }
        });

        // 去除掉审核后不允许编辑的字段
        vos.removeIf(field -> !Objects.equals(1, field.getCheckOkEdit()));

        if(vos.size() <= 0){
            throw new CrmException(CrmCodeEnum.CRM_REFUND_NOT_CHECK_OK_EDIT);
        }

        return vos;
    }

    /**
     * 分页查询
     *
     * @param search
     * @return
     */
    @Override
    public BasePage<Map<String, Object>> queryPageList(CrmSearchBO search) {

        search.setLabel(CrmEnum.REFUND.getType());

        BasePage<Map<String, Object>> basePage = queryList(search);

        basePage.getList().forEach(map -> {
            //创建人名称回显
            if(ObjectUtil.isNotEmpty(map.get("createUserId"))){
                Long createUserId = Long.valueOf(String.valueOf(map.get("createUserId")));
                if(ObjectUtil.isNotEmpty(createUserId)){
                    String createUserName = UserCacheUtil.getUserName(createUserId);
                    map.put("createUserName",createUserName);
                }
            }

            // 负责人名称回显
            if(ObjectUtil.isNotEmpty(map.get("ownerUserId"))){
                Long ownerUserId = Long.valueOf(String.valueOf(map.get("ownerUserId")));
                if(ObjectUtil.isNotEmpty(ownerUserId)){
                    String ownerUserName = UserCacheUtil.getUserName(ownerUserId);
                    map.put("ownerUserName",ownerUserName);
                }
            }

            // 退款负责人名称回显
            if(ObjectUtil.isNotEmpty(map.get("refundUserId"))){
                Long refundUserId = Long.valueOf(String.valueOf(map.get("refundUserId")));
                if(ObjectUtil.isNotEmpty(refundUserId)){
                    String refundUserName = UserCacheUtil.getUserName(refundUserId);
                    map.put("refundUserName",refundUserName);
                }
            }

            if (ObjectUtil.isNotEmpty(map.get("teacherId"))) {
                // 营销讲师名称回显
                Long teacherId = Long.valueOf(String.valueOf(map.get("teacherId")));
                if (ObjectUtil.isNotEmpty(teacherId)) {
                    String teacherName = UserCacheUtil.getUserName(teacherId);
                    map.put("teacherName", teacherName);
                }
            }


            //负责人所在部门
            if (ObjectUtil.isNotEmpty(map.get("ownerDeptId"))) {
                Long ownerDeptId = Long.valueOf(String.valueOf(map.get("ownerDeptId")));
                if (ObjectUtil.isNotEmpty(ownerDeptId)) {
                    String ownerDeptName = adminService.queryDeptName(Integer.valueOf(ownerDeptId.toString()));
                    map.put("ownerDeptName", ownerDeptName);
                }
            }

            if(ObjectUtil.isEmpty(map.get("studentId"))){
                map.put("studentName", "");
            }

        });

        SearchRequest searchRequest = new SearchRequest(getIndex());
        searchRequest.types(getDocType());
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder queryBuilder = createQueryBuilder(search);
        List<Integer> checkStatusList = new ArrayList<>();
        checkStatusList.add(1);
        checkStatusList.add(3);
        queryBuilder.must(QueryBuilders.termsQuery("checkStatus", checkStatusList));
//        queryBuilder.should(QueryBuilders.termQuery("checkStatus",1))
        sourceBuilder.query(queryBuilder);
        sourceBuilder.aggregation(AggregationBuilders.sum("money").field("money"))
                .aggregation(AggregationBuilders.sum("contractMoney").field("contractMoney"))
                .aggregation(AggregationBuilders.sum("receivablesMoney").field("receivablesMoney"))
                .aggregation(AggregationBuilders.sum("billMoney").field("billMoney"));
        searchRequest.source(sourceBuilder);
        try {
            SearchResponse searchCount = elasticsearchRestTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);
            Aggregations aggregations = searchCount.getAggregations();
            Map<String, Object> countMap = new HashMap<>();
            ParsedSum refundMoney = aggregations.get("money");
            ParsedSum contractMoney = aggregations.get("contractMoney");
            ParsedSum receivablesMoney = aggregations.get("receivablesMoney");
            ParsedSum billMoney = aggregations.get("billMoney");
            countMap.put("refundMoney",refundMoney.getValue());
            countMap.put("contractMoney",contractMoney.getValue());
            countMap.put("receivablesMoney",receivablesMoney.getValue());
            countMap.put("billMoney",billMoney.getValue());
            basePage.setExtraData(new JSONObject().fluentPut("money",countMap));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return basePage;
    }

    /**
     * 查询字段配置
     * @param id 主键ID
     * @return data
     */
    @Override
    public CrmModel queryById(Integer id) {
        CrmModel crmModel;
        if (id != null) {
            crmModel = getBaseMapper().queryById(id, UserUtil.getUserId());
            crmModel.setLabel(CrmEnum.REFUND.getType());
            crmModel.setOwnerUserName(UserCacheUtil.getUserName(crmModel.getOwnerUserId()));
            crmModel.put("ownerUserName", UserCacheUtil.getUserName((Long) crmModel.get("ownerUserId")));
            if(BeanUtil.isNotEmpty(crmModel.get("crmDeptId"))){
                crmModel.put("ownerDeptName", this.adminService.queryDeptName(Integer.valueOf(String.valueOf(crmModel.get("ownerDeptId")))));
            }else{
                if(ObjectUtil.isNotEmpty(UserCacheUtil.getUserInfo((Long)crmModel.get("ownerUserId")))){
                    Integer deptId = UserCacheUtil.getUserInfo((Long)crmModel.get("ownerUserId")).getDeptId();
                    crmModel.put("ownerDeptName", this.adminService.queryDeptName(deptId));
                }
            }
            crmRefundDataService.setDataByBatchId(crmModel);
            List<String> stringList = SpringUtils.getBean(ICrmRoleFieldService.class).queryNoAuthField(crmModel.getLabel());
            List<String> deptFieldList = SpringUtils.getBean(ICrmDeptFieldService.class).queryNoAuthField(crmModel.getLabel());
            stringList = stringList.stream().filter(field -> deptFieldList.contains(field)).collect(Collectors.toList());

            stringList = stringList.stream().distinct().collect(Collectors.toList());
            stringList.forEach(crmModel::remove);
        } else {
            crmModel = new CrmModel(CrmEnum.REFUND.getType());
        }
        return crmModel;
    }

    /**
     * 保存或新增信息
     *
     * @param crmModel model
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addOrUpdate(CrmContractSaveBO crmModel) {
        if(String.valueOf(crmModel.getEntity().get("ownerUserId")).split(",").length > 1){
            throw new CrmException(CrmCodeEnum.CRM_RECEIVABLES_OWNER_USER_TOO_LONG);
        }

        CrmRefund crmRefund = BeanUtil.copyProperties(crmModel.getEntity(), CrmRefund.class);

        if(StringUtils.isEmpty(crmRefund.getReturnType())){
            throw new CrmException(CrmCodeEnum.CRM_REFUND_PAYMENT_DICT_SELECT);
        }

        CrmContract crmContract = crmContractService.getById(crmRefund.getContractId());

        QueryWrapper<CrmReceivables> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("contract_id",crmRefund.getContractId());
        queryWrapper.eq("check_status",1);
        List<CrmReceivables> crmReceivables = crmReceivablesService.getBaseMapper().selectList(queryWrapper);
        if(CollectionUtil.isEmpty(crmReceivables)){
            throw new CrmException(CrmCodeEnum.CRM_REFUND_NOT_HAVE_RECEIVABLES);
        }

        if (crmContract == null || !crmContract.getCheckStatus().equals(1)) {
            throw new CrmException(CrmCodeEnum.CRM_REFUND_ADD_ERROR);
        }
        //购买课程
        if (StringUtils.isNotBlank(crmContract.getCourseSource())){
            crmRefund.setCourseSource(crmContract.getCourseSource());
        }

        if(BeanUtil.isEmpty(crmRefund.getCreateUserId())){
            crmRefund.setCreateUserId(UserUtil.getUserId());
        }
        if(crmContract.getLeadsFormTime() != null){
            crmRefund.setLeadsFormTime(crmContract.getLeadsFormTime());
        }

        // 实际回款金额应大于0
        if(crmRefund.getMoney().doubleValue() < 0){
            throw new CrmException(CrmCodeEnum.CRM_REFUND_MONEY_ZERO);
        }

        String batchId = StrUtil.isNotEmpty(crmRefund.getBatchId()) ? crmRefund.getBatchId() : IdUtil.simpleUUID();
        actionRecordUtil.updateRecord(crmModel.getField(), Dict.create().set("batchId", batchId).set("dataTableName", "bill_crm_business_data"));
        crmRefundDataService.saveData(crmModel.getField(), batchId);
        ExamineRecordSaveBO examineRecordSaveBO = crmModel.getExamineFlowData();

        ExamineRecordReturnVO examineData = null;

        boolean isUpdate = false;
        CrmRefund oldRefund = new CrmRefund();
        if (crmRefund.getRefundId() == null) {
            List<AdminConfigBo> configList = adminService.queryConfigByName("numberSetting");
            AdminConfigBo adminConfig = configList.stream().filter(config -> Objects.equals(getLabel().getType().toString(), config.getValue())).collect(Collectors.toList()).get(0);
            if (adminConfig.getStatus() == 1 && StrUtil.isEmpty(crmRefund.getNumber())) {
                String result = crmNumberSettingService.generateNumber(adminConfig, null);
                if(BeanUtil.isEmpty(crmRefund.getNumber())){
                    crmRefund.setNumber(result);
                }
            }
            Integer count = lambdaQuery().eq(CrmRefund::getNumber, crmRefund.getNumber()).ne(CrmRefund::getCheckStatus, 7).count();
            if (count != null && count > 0) {
                throw new CrmException(CrmCodeEnum.CRM_REFUND_NUM_ERROR);
            }
            if(BeanUtil.isEmpty(crmRefund.getCreateTime())){
                crmRefund.setCreateTime(DateUtil.date());
            }
            if(BeanUtil.isEmpty(crmRefund.getUpdateTime())){
                crmRefund.setUpdateTime(DateUtil.date());
            }
            crmRefund.setBatchId(batchId);

            //负责人ID
            if(BeanUtil.isEmpty(crmRefund.getOwnerUserId())){
                Object owner_user_id = crmModel.getEntity().get("owner_user_id");
                if (ObjectUtil.isAllNotEmpty(owner_user_id)){
                    crmRefund.setOwnerUserId((Long) owner_user_id);
                }else{
                    crmRefund.setOwnerUserId(UserUtil.getUserId());
                }
            }

            // 获取VIP学员Id
            CrmStudent student = crmStudentService.getById(crmRefund.getStudentId());
            if(ObjectUtil.isNotEmpty(student)){
                //设置数据来源
                crmRefund.setSource(student.getSource());
                //是否重复
                crmRefund.setIsRepetition(student.getIsRepetition());
            }
            CrmCustomer customer = crmCustomerService.queryCustomerBySerialNumber(student.getSerialNumber());
            if(ObjectUtil.isNotEmpty(customer)){
                crmRefund.setCustomerId(customer.getCustomerId());
            }else{
                throw new CrmException(CrmCodeEnum.CRM_REFUND_NOT_HAVE_CUSTOMER);
            }

            crmRefund.setRefundCategory(CrmBusinessConstEnum.退款状态_全款退款.getMsg());
            crmRefund.setContractCategory(crmContract.getContractCategory());

            //设置负责人所在部门
            crmRefund.setOwnerDeptId(String.valueOf(UserCacheUtil.getUserInfo(crmRefund.getOwnerUserId()).getDeptId()));

            save(crmRefund);
            if (crmRefund.getCheckStatus() == null || crmRefund.getCheckStatus() != 5) {
                if (examineRecordSaveBO != null) {
                    this.supplementFieldInfo(13, crmRefund.getRefundId(), null, examineRecordSaveBO);
                    examineRecordSaveBO.setTitle(crmRefund.getNumber());
                    examineRecordSaveBO.setSubmitUserId(UserUtil.getUserId());
                    examineData = examineService.addExamineRecord(examineRecordSaveBO);
                    crmRefund.setExamineRecordId(examineData.getRecordId());
                    crmRefund.setCheckStatus(examineData.getExamineStatus());

                } else {
                    crmRefund.setCheckStatus(1);
                    crmRefund.setRefundDate(DateUtil.date());
                }
            }
            updateById(crmRefund);

            if(crmRefund.getCheckStatus() == 1){
                updateCustomerDeal(crmRefund);
            }

            crmActivityService.addActivity(2, CrmActivityEnum.REFUND, crmRefund.getRefundId());
            actionRecordUtil.addRecord(crmRefund.getRefundId(), CrmEnum.REFUND, crmRefund.getNumber());
        } else {
            isUpdate = true;
            CrmRefund refund = getById(crmRefund.getRefundId());
            BeanUtils.copyProperties(refund, oldRefund);
            if (!refund.getCreateUserId().equals(UserUtil.getUserId()) && examineRecordSaveBO != null) {
                throw new CrmException(CrmCodeEnum.CRM_REFUND_EDIT_ERROR);
            }
            if (refund.getCheckStatus() == 1){
                throw new CrmException(CrmCodeEnum.CRM_REFUND_EXAMINE_PASS_ERROR);
            }
            if (refund.getCheckStatus() != 4 && refund.getCheckStatus() != 2 && refund.getCheckStatus() != 5) {
                throw new CrmException(CrmCodeEnum.CRM_CONTRACT_EDIT_ERROR);
            }

            if (crmRefund.getCheckStatus() == null || crmRefund.getCheckStatus() != 5) {
                if (examineRecordSaveBO != null) {
                    this.supplementFieldInfo(13, refund.getRefundId(), refund.getExamineRecordId(), examineRecordSaveBO);
                    examineRecordSaveBO.setTitle(refund.getNumber());
                    examineRecordSaveBO.setSubmitUserId(UserUtil.getUserId());
                    examineData = examineService.addExamineRecord(examineRecordSaveBO);
                    crmRefund.setExamineRecordId(examineData.getRecordId());
                    crmRefund.setCheckStatus(examineData.getExamineStatus());
                } else {
                    crmRefund.setCheckStatus(1);
                    if (refund.getCheckStatus() != 1) {
                        examineRecordService.updateContractMoney(crmRefund.getRefundId());
                    }
                }
            }

            crmRefund.setUpdateTime(DateUtil.date());
            /*CrmReceivablesPlan crmReceivablesPlan = crmReceivablesPlanService.getById(crmRefund.getPlanId());
            if (crmReceivablesPlan != null) {
                crmReceivablesPlan.setReceivablesId(crmRefund.getReceivablesId());
                crmReceivablesPlan.setUpdateTime(DateUtil.date());
                crmReceivablesPlanService.updateById(crmReceivablesPlan);
            }*/
            actionRecordUtil.updateRecord(BeanUtil.beanToMap(refund), BeanUtil.beanToMap(crmRefund), CrmEnum.CONTRACT, crmContract.getName(), crmContract.getContractId());
            updateById(crmRefund);
            crmRefund = getById(crmRefund.getRefundId());

            /*if(crmRefund.getCheckStatus() == 1 || crmRefund.getCheckStatus() == 3){
                //根据合同Id获取合同下审核通过及审核中的回款金额
                BigDecimal sumMoney = baseMapper.querySumMoneyByContractId(crmRefund.getContractId());
                //合同下回款审核通过及审核中金额大于等于500修改合同成交
                if(sumMoney.doubleValue() >= 1){
                    if(crmContract.getMoney().subtract(sumMoney).compareTo(BigDecimal.ZERO) <= 0){
                        crmContract.setBackStatus("已回款");
                    }else {
                        crmContract.setBackStatus("回款中");
                    }
                    crmContract.setReceivedMoney(sumMoney);
                    crmContract.setUninvoicedMonery(crmContract.getMoney().subtract(sumMoney));
                    updateContractDealStatus(crmContract,"已成交");
                }
            }*/
        }
        crmModel.setEntity(BeanUtil.beanToMap(crmRefund));
        savePage(crmModel, crmRefund.getRefundId(),false);

        if(isUpdate){
            if(!ObjectUtil.equal(oldRefund.getOwnerUserId(), crmRefund.getOwnerUserId())){
                String ownerUserName = UserCacheUtil.getUserName(crmRefund.getOwnerUserId());

                if(oldRefund.getOwnerUserId() != null){
                    addMessage(oldRefund.getNumber(),ownerUserName,oldRefund.getOwnerUserId(),AdminMessageEnum.CRM_REFUND_CHANGE_OWNER_USER.getType(),crmRefund.getRefundId());
                }
                if(crmRefund.getOwnerUserId() != null){
                    addMessage(oldRefund.getNumber(),ownerUserName,crmRefund.getOwnerUserId(),AdminMessageEnum.CRM_REFUND_CHANGE_OWNER_USER.getType(),crmRefund.getRefundId());
                }
            }

            if(!ObjectUtil.equal(oldRefund.getTeacherId(), crmRefund.getTeacherId())){
                String teacherName = UserCacheUtil.getUserName(crmRefund.getTeacherId());

                if(oldRefund.getTeacherId() != null){
                    addMessage(oldRefund.getNumber(),teacherName,oldRefund.getTeacherId(),AdminMessageEnum.CRM_REFUND_CHANGE_TEACHER_USER.getType(),crmRefund.getRefundId());
                }

                if(crmRefund.getTeacherId() != null){
                    addMessage(oldRefund.getNumber(),teacherName,crmRefund.getTeacherId(),AdminMessageEnum.CRM_REFUND_CHANGE_TEACHER_USER.getType(),crmRefund.getRefundId());
                }
            }

            if(!ObjectUtil.equal(oldRefund.getRefundUserId(), crmRefund.getRefundUserId())){
                String refundUserName = UserCacheUtil.getUserName(crmRefund.getRefundUserId());

                if(oldRefund.getRefundUserId() != null){
                    addMessage(oldRefund.getNumber(),refundUserName,oldRefund.getRefundUserId(),AdminMessageEnum.CRM_REFUND_CHANGE_REFUND_USER.getType(),crmRefund.getRefundId());
                }
                if(crmRefund.getRefundUserId() != null){
                    addMessage(oldRefund.getNumber(),refundUserName,crmRefund.getRefundUserId(),AdminMessageEnum.CRM_REFUND_CHANGE_REFUND_USER.getType(),crmRefund.getRefundId());
                }
            }
        }

    }



    /**
     * 保存或新增信息
     *
     * @param crmModel model
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void checkOkEdit(CrmContractSaveBO crmModel) {
        CrmRefund crmRefund = BeanUtil.copyProperties(crmModel.getEntity(), CrmRefund.class);

        if(ObjectUtil.isNotEmpty(crmRefund.getContractId())){
            CrmContract crmContract = crmContractService.getById(crmRefund.getContractId());

            QueryWrapper<CrmReceivables> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("contract_id",crmRefund.getContractId());
            queryWrapper.eq("check_status",1);
            List<CrmReceivables> crmReceivables = crmReceivablesService.getBaseMapper().selectList(queryWrapper);
            if(CollectionUtil.isEmpty(crmReceivables)){
                throw new CrmException(CrmCodeEnum.CRM_REFUND_NOT_HAVE_RECEIVABLES);
            }
            if (crmContract == null || !crmContract.getCheckStatus().equals(1)) {
                throw new CrmException(CrmCodeEnum.CRM_REFUND_ADD_ERROR);
            }
        }
        // 实际回款金额应大于0
        if(ObjectUtil.isNotEmpty(crmRefund.getMoney()) && crmRefund.getMoney().doubleValue() < 0){
            throw new CrmException(CrmCodeEnum.CRM_REFUND_MONEY_ZERO);
        }
        String batchId = StrUtil.isNotEmpty(crmRefund.getBatchId()) ? crmRefund.getBatchId() : IdUtil.simpleUUID();
        crmRefundDataService.saveCheckOkEditData(crmModel.getField(), batchId);

        CrmRefund refund = getById(crmRefund.getRefundId());

        //设置负责人所在部门
        if(BeanUtil.isNotEmpty(crmRefund.getOwnerUserId())){
            crmRefund.setOwnerDeptId(String.valueOf(UserCacheUtil.getUserInfo(crmRefund.getOwnerUserId()).getDeptId()));
        }

        crmRefund.setUpdateTime(DateUtil.date());

        Map<String, Object> crmRefundMap = BeanUtil.beanToMap(crmRefund);
        Map<String, Object> refundMap = new HashMap<>();
        crmRefundMap.keySet().forEach(item -> {
            if(ObjectUtil.isNotEmpty(crmRefundMap.get(item))){
                refundMap.put(item, crmRefundMap.get(item));
            }
        });
        Map<String, Object> oldRefundMap = BeanUtil.beanToMap(refund);
        Set<String> hashSet = new HashSet<>(refundMap.keySet());
        hashSet.retainAll(oldRefundMap.keySet());
        refundMap.keySet().retainAll(hashSet);
        oldRefundMap.keySet().retainAll(hashSet);

        actionRecordUtil.updateRecord(oldRefundMap, refundMap, CrmEnum.REFUND, crmRefund.getNumber(), crmRefund.getRefundId());
        updateById(crmRefund);
        crmRefund = getById(crmRefund.getRefundId());

        crmModel.setEntity(BeanUtil.beanToMap(crmRefund));
        List<String> fieldNameList = new ArrayList<>();
        if(!CollectionUtil.isEmpty(crmModel.getField())){
            List<String> fieldName = crmModel.getField().stream().map(CrmModelFiledVO::getFieldName).collect(Collectors.toList());
            fieldNameList.addAll(fieldName);
        }

        List<CrmRefundData> refundDataList = crmRefundDataService.query().eq("batch_id", batchId).list();
        refundDataList.forEach(obj -> {
            if(!CollectionUtil.isEmpty(fieldNameList)){
                if(!fieldNameList.contains(obj.getName())){
                    crmModel.getEntity().put(obj.getName(), obj.getValue());
                }
            }else{
                crmModel.getEntity().put(obj.getName(), obj.getValue());
            }
        });

        savePage(crmModel, crmRefund.getRefundId(),false);
    }

    /**
     * 修改回款信息
     * @param crmRefund
     */
    public void updateMoney(CrmRefund crmRefund){
        updateById(crmRefund);
        Map<String, Object> data = BeanUtil.copyProperties(crmRefund, HashMap.class);
        CrmContractSaveBO crmModel = new CrmContractSaveBO();
        List<CrmReceivablesData> dataList = SpringUtils.getBean(CrmReceivablesDataMapper.class).queryReceivablesDataByBatchId(crmRefund.getBatchId());

        List<CrmModelFiledVO> crmModelFiledVOList = new ArrayList<>();
        for(int i=0;i<dataList.size();i++){
            CrmModelFiledVO c = new CrmModelFiledVO();
            c.setFieldId(dataList.get(i).getFieldId());
            c.setValue(dataList.get(i).getValue());
            c.setFieldName(dataList.get(i).getName());
            crmModelFiledVOList.add(c);
        }
        crmModel.setField(crmModelFiledVOList);
        crmModel.setEntity(data);
        savePage(crmModel, crmRefund.getRefundId(),false);
    }

    @Override
    public void setOtherField(Map<String, Object> map) {
//        String customerName = crmCustomerService.getCustomerName((Integer) map.get("customerId"));
//        map.put("customerName", customerName);
        String studentName = crmStudentService.getCustomerName((Integer) map.get("studentId"));
        map.put("studentName", studentName);
        CrmContract contract = crmContractService.getById((Serializable) map.get("contractId"));
        if (contract != null) {
            map.put("contractNum", contract.getNum());
            map.put("contractMoney", contract.getMoney());
        }
        /*CrmReceivables receivables = crmReceivablesService.getById((Serializable) map.get("receivablesId"));
        if(receivables != null){
            map.put("receivablesNum", receivables.getNumber());
            map.put("receivablesMoney", receivables.getMoney());
        }*/
        String ownerUserName = UserCacheUtil.getUserName((Long) map.get("ownerUserId"));
        map.put("ownerUserName", ownerUserName);
        String refundUserName = UserCacheUtil.getUserName((Long) map.get("refundUserId"));
        map.put("refundUserName", refundUserName);
        String createUserName = UserCacheUtil.getUserName((Long) map.get("createUserId"));
        map.put("createUserName", createUserName);
        String deptName = "";
        if(BeanUtil.isNotEmpty(map.get("ownerDeptId"))){
            deptName = this.adminService.queryDeptName(Integer.valueOf(String.valueOf(map.get("ownerDeptId"))));
        }
        map.put("ownerDeptName",deptName);
        Integer planId = (Integer) map.get("planId");
        if (planId != null) {
            map.put("planNum", crmReceivablesPlanService.query().select("num").eq("plan_id", planId).one().getNum());
        }

        String teacherName = UserCacheUtil.getUserName((Long) map.get("teacherId"));
        map.put("teacherName", teacherName);
    }

    @Override
    public Dict getSearchTransferMap() {
        return Dict.create()
                .set("studentId", "studentName").set("contractId", "contractNum").set("planId","planNum").set("teacherId", "teacherName");
    }

    /**
     * 删除回款数据
     *
     * @param ids ids
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByIds(List<Integer> ids) {
        for (Integer id : ids) {
            CrmRefund refund = getById(id);
            boolean bol = (refund.getCheckStatus() != 4 && refund.getCheckStatus() != 5) && ! (UserUtil.isAdmin());
            if (bol) {
                throw new CrmException(CrmCodeEnum.CAN_ONLY_DELETE_WITHDRAWN_AND_SUBMITTED_EXAMINE);
            }
            /*if (receivables.getCheckStatus() == 1 || receivables.getCheckStatus() == 3) {
                examineRecordService.updateUnreceivedMoney(id);
                //是否需要更新合同成交状态
                changeCustomerStatus(receivables);
                //还原合同金额
            }*/
            if(CrmBusinessConstEnum.退款状态_账单退款.getMsg().equals(refund.getRefundCategory())){
                throw new CrmException(CrmCodeEnum.CRM_ORDER_REFUND_IS_NOT_DELETE);
            }
            //删除跟进记录
            crmActivityService.deleteActivityRecord(CrmActivityEnum.REFUND, Collections.singletonList(id));
            //删除字段操作记录
            crmActionRecordService.deleteActionRecord(CrmEnum.REFUND, Collections.singletonList(refund.getRefundId()));

            //删除自定义字段
            crmRefundDataService.deleteByBatchId(Collections.singletonList(refund.getBatchId()));
            //删除文件
            adminFileService.delete(Collections.singletonList(refund.getBatchId()));
            if (ObjectUtil.isNotEmpty(refund.getExamineRecordId())) {
                examineService.deleteExamineRecord(refund.getExamineRecordId());
            }
            IS_DELETE = false;

            refund.setCheckStatus(7);
            updateById(refund);

            //更新客户回款状态
            if(refund.getCheckStatus() != 2 && refund.getCheckStatus() != 4 && refund.getCheckStatus() != 5){
                updateCustomerDeal(refund);
            }else{
                updateCustomerDeal(refund);
            }
        }
        deletePage(ids);
    }

    /**
     * 修改回款负责人
     *
     * @param refundIds 退款id列表
     * @param newOwnerUserId 新负责人ID
     */
    @Override
    public void changeOwnerUser(List<Integer> refundIds, Long newOwnerUserId) {
        QueryWrapper<CrmRefund> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("refund_id", refundIds);
        queryWrapper.notIn("check_status", 7);
        List<CrmRefund> crmRefundList = query().getBaseMapper().selectList(queryWrapper);

        LambdaUpdateWrapper<CrmRefund> wrapper = new LambdaUpdateWrapper<>();
        wrapper.in(CrmRefund::getRefundId, refundIds);
        wrapper.set(CrmRefund::getOwnerUserId, newOwnerUserId);
        update(wrapper);
        for (Integer id : refundIds) {
            actionRecordUtil.addConversionRecord(id,CrmEnum.REFUND,newOwnerUserId,getById(id).getNumber());
        }
        Integer deptId = adminService.getUserInfo(newOwnerUserId).getDeptId();
        //修改es
        updateField("ownerUserId", newOwnerUserId, refundIds);
        updateField("ownerDeptId", deptId, refundIds);

        String ownerUserName = UserCacheUtil.getUserName(newOwnerUserId);
        for(CrmRefund refund : crmRefundList){
            if(!ObjectUtil.equal(refund.getOwnerUserId(),newOwnerUserId)){
                if((!UserUtil.getUserId().equals(refund.getOwnerUserId())) && (refund.getOwnerUserId() != null)){
                    addMessage(refund.getNumber(),ownerUserName,refund.getOwnerUserId(),AdminMessageEnum.CRM_REFUND_CHANGE_OWNER_USER.getType(),refund.getRefundId());
                }

                if(newOwnerUserId != null){
                    addMessage(refund.getNumber(),ownerUserName,newOwnerUserId,AdminMessageEnum.CRM_REFUND_CHANGE_OWNER_USER.getType(),refund.getRefundId());
                }
            }
        }
    }

    /**
     * 修改退款负责人
     *
     * @param refundIds 退款id列表
     * @param newRefundUserId 新负责人ID
     */
    @Override
    public void changeRefundUser(List<Integer> refundIds, Long newRefundUserId) {
        QueryWrapper<CrmRefund> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("refund_id", refundIds);
        queryWrapper.notIn("check_status", 7);
        List<CrmRefund> crmRefundList = query().getBaseMapper().selectList(queryWrapper);

        LambdaUpdateWrapper<CrmRefund> wrapper = new LambdaUpdateWrapper<>();
        wrapper.in(CrmRefund::getRefundId, refundIds);
        wrapper.set(CrmRefund::getRefundUserId, newRefundUserId);
        update(wrapper);
        for (Integer id : refundIds) {
            actionRecordUtil.addConversionRecord(id,CrmEnum.REFUND,newRefundUserId,getById(id).getNumber());
        }
        //修改es
        updateField("refundUserId", newRefundUserId, refundIds);

        String refundUserName = UserCacheUtil.getUserName(newRefundUserId);
        for(CrmRefund refund : crmRefundList){
            if(!ObjectUtil.equal(refund.getRefundUserId(),newRefundUserId)){
                if((!UserUtil.getUserId().equals(refund.getRefundUserId())) && (refund.getRefundUserId() != null)){
                    addMessage(refund.getNumber(),refundUserName,refund.getRefundUserId(),AdminMessageEnum.CRM_REFUND_CHANGE_REFUND_USER.getType(),refund.getRefundId());
                }

                if((!UserUtil.getUserId().equals(newRefundUserId)) && newRefundUserId != null){
                    addMessage(refund.getNumber(),refundUserName,newRefundUserId,AdminMessageEnum.CRM_REFUND_CHANGE_REFUND_USER.getType(),refund.getRefundId());
                }
            }
        }
    }

    /**
     * 修改退款讲师负责人
     * @param ownerUserBO
     */
    @Override
    public void changeTeacherUser(CrmChangeOwnerUserBO ownerUserBO){
        QueryWrapper<CrmRefund> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("refund_id", ownerUserBO.getIds());
        queryWrapper.notIn("check_status", 7);
        List<CrmRefund> crmRefundList = query().getBaseMapper().selectList(queryWrapper);

        LambdaUpdateWrapper<CrmRefund> wrapper = new LambdaUpdateWrapper<>();
        wrapper.in(CrmRefund::getRefundId, ownerUserBO.getIds());
        wrapper.set(CrmRefund::getTeacherId, ownerUserBO.getTeacherId());
        update(wrapper);

        // 操作记录
        for (Integer id : ownerUserBO.getIds()) {
            actionRecordUtil.conversionTeacherRecordAdd(id,CrmEnum.REFUND,ownerUserBO.getTeacherId(),getById(id).getNumber());
        }

        //修改es
        updateField("teacherId", ownerUserBO.getTeacherId(), ownerUserBO.getIds());

        String teacherName = UserCacheUtil.getUserName(ownerUserBO.getTeacherId());
        // 发送消息
        for(CrmRefund refund : crmRefundList){
            if(!ObjectUtil.equal(refund.getTeacherId(),ownerUserBO.getTeacherId())){
                if((!UserUtil.getUserId().equals(refund.getTeacherId())) && (refund.getTeacherId() != null)){
                    addMessage(refund.getNumber(),teacherName,refund.getTeacherId(),AdminMessageEnum.CRM_REFUND_CHANGE_TEACHER_USER.getType(),refund.getRefundId());
                }

                if((!UserUtil.getUserId().equals(ownerUserBO.getTeacherId())) && ownerUserBO.getTeacherId() != null){
                    addMessage(refund.getNumber(),teacherName,ownerUserBO.getTeacherId(),AdminMessageEnum.CRM_REFUND_CHANGE_TEACHER_USER.getType(),refund.getRefundId());
                }
            }
        }
    }

    /**
     * 导出
     *
     * @param response resp
     * @param search   搜索对象
     */
    @Override
    public void exportExcel(HttpServletResponse response, CrmSearchBO search) {
        List<Map<String, Object>> dataList = queryPageList(search).getList();
        try (ExcelWriter writer = ExcelUtil.getWriter()) {
            List<CrmFieldSortVO> headList = crmFieldService.queryListHead(getLabel().getType());
            headList.removeIf(crmFieldSortVO -> "refundMaterial".equals(crmFieldSortVO.getFieldName()));
            headList.forEach(head -> writer.addHeaderAlias(head.getFieldName(), head.getName()));
            writer.merge(headList.size() - 1, "退款信息");
            if (dataList.size() == 0) {
                Map<String, Object> record = new HashMap<>();
                headList.forEach(head -> record.put(head.getFieldName(), ""));
                dataList.add(record);
            }
            dataList.forEach(record -> {
                if (record.get("checkStatus") == null || "".equals(record.get("checkStatus"))) {
                    return;
                }else{
                    String checkStatus;
                    //0待审核、1通过、2拒绝、3审核中 4:撤回 5 未提交
                    switch ((Integer) record.get("checkStatus")) {
                        case 1:
                            checkStatus = "通过";
                            break;
                        case 2:
                            checkStatus = "拒绝";
                            break;
                        case 3:
                            checkStatus = "审核中";
                            break;
                        case 4:
                            checkStatus = "撤回";
                            break;
                        case 5:
                            checkStatus = "未提交";
                            break;
                        case 7:
                            checkStatus = "已删除";
                            break;
                        default:
                            checkStatus = "待审核";
                    }
                    record.put("checkStatus", checkStatus);
                }

                if(record.get("categories") != null){
                    String categories = "";
                    if(Integer.valueOf(1).equals(record.get("categories"))){
                        categories = "电商美工";
                    }else if(Integer.valueOf(2).equals(record.get("categories"))){
                        categories = "手绘插画";
                    }else if(Integer.valueOf(3).equals(record.get("categories"))){
                        categories = "影视后期";
                    }
                    record.put("categories", categories);
                }

                if(record.get("salesType") != null){
                    String salesType = "";
                    if(Integer.valueOf(1).equals(record.get("salesType"))){
                        salesType = "电销";
                    }else if(Integer.valueOf(2).equals(record.get("salesType"))){
                        salesType = "网销";
                    }
                    record.put("salesType", salesType);
                }

                if(record.get("bankCardAddr") != null){
                    JSONObject addrJson = JSONObject.parseObject((String) record.get("bankCardAddr"));
                    if(addrJson != null){
                        String province = String.valueOf(addrJson.get("province"));
                        String city = String.valueOf(addrJson.get("city"));
                        String area = String.valueOf(addrJson.get("area"));
                        if(StringUtils.isNotEmpty(province) || StringUtils.isNotEmpty(city) || StringUtils.isNotEmpty(area)){
                            record.put("bankCardAddr", province + "|" + city + "|" + area);
                        }else if(StringUtils.isNotEmpty(province) || StringUtils.isNotEmpty(city)){
                            record.put("bankCardAddr", province + "|" + city);
                        }else {
                            record.put("bankCardAddr", province);
                        }
                    }else{
                        record.put("bankCardAddr", "");
                    }
                }

            });
            writer.setOnlyAlias(true);
            writer.write(dataList, true);
            writer.setRowHeight(0, 20);
            writer.setRowHeight(1, 20);
            for (int i = 0; i < headList.size(); i++) {
                writer.setColumnWidth(i, 20);
            }
            Cell cell = writer.getCell(0, 0);
            CellStyle cellStyle = cell.getCellStyle();
            cellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            Font font = writer.createFont();
            font.setBold(true);
            font.setFontHeightInPoints((short) 16);
            cellStyle.setFont(font);
            cell.setCellStyle(cellStyle);
            //自定义标题别名
            //response为HttpServletResponse对象
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setCharacterEncoding("UTF-8");
            //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
            String fileName = "退款" + DateUtils.dateTimeNow() + ".xls";
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName,"UTF-8"));
            ServletOutputStream out = response.getOutputStream();
            writer.flush(out);

            // 新增消息
            addMessage(dataList.size() <=0 ? "0" : String.valueOf(dataList.size()),"导出数据" + String.valueOf(dataList.size()) + "条",UserUtil.getUserId(),AdminMessageEnum.CRM_REFUND_EXPORT.getType(),null);

        } catch (Exception e) {
            log.error("导出退款错误：", e);
        }
    }

    /**
     * 查询文件数量
     *
     * @param id id
     * @return data
     */
    @Override
    public CrmInfoNumVO num(Integer id) {
        List<String> batchIdList = new ArrayList<>();
        CrmRefund crmRefund = getById(id);
        AdminFileService fileService = SpringUtils.getBean(AdminFileService.class);
        List<CrmField> crmFields = crmFieldService.queryFileField();
        if (crmFields.size() > 0) {
            LambdaQueryWrapper<CrmRefundData> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(CrmRefundData::getValue);
            wrapper.eq(CrmRefundData::getBatchId, crmRefund.getBatchId());
            wrapper.in(CrmRefundData::getFieldId, crmFields.stream().map(CrmField::getFieldId).collect(Collectors.toList()));
            batchIdList.addAll(crmRefundDataService.listObjs(wrapper, Object::toString));
        }
        if(StringUtils.isNotBlank(crmRefund.getBatchId())){
            batchIdList.add(crmRefund.getBatchId());
        }
        if(StringUtils.isNotBlank(crmRefund.getRefundMaterial())){
            batchIdList.add(crmRefund.getRefundMaterial());
        }
        CrmInfoNumVO numVO = new CrmInfoNumVO();
        numVO.setFileCount(fileService.queryNum(batchIdList));
        return numVO;
    }

    /**
     * 查询文件列表
     *
     * @param id id
     * @return file
     */
    @Override
    public List<FileEntity> queryFileList(Integer id) {
        List<FileEntity> fileEntityList = new ArrayList<>();
        CrmRefund crmRefund = getById(id);
        AdminFileService fileService = SpringUtils.getBean(AdminFileService.class);

        fileService.queryFileList(crmRefund.getRefundMaterial()).forEach(fileEntity -> {
            fileEntity.setSource("退款资料");
            fileEntity.setReadOnly(1);
            fileEntityList.add(fileEntity);
        });

        fileService.queryFileList(crmRefund.getBatchId()).forEach(fileEntity -> {
            fileEntity.setSource("附件上传");
            fileEntity.setReadOnly(0);
            fileEntityList.add(fileEntity);
        });
        List<CrmField> crmFields = crmFieldService.queryFileField();
        if (crmFields.size() > 0) {
            LambdaQueryWrapper<CrmRefundData> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(CrmRefundData::getValue);
            wrapper.eq(CrmRefundData::getBatchId, crmRefund.getBatchId());
            wrapper.in(CrmRefundData::getFieldId, crmFields.stream().map(CrmField::getFieldId).collect(Collectors.toList()));
            List<FileEntity> data = fileService.queryFileList(crmRefundDataService.listObjs(wrapper, Object::toString));
            data.forEach(fileEntity -> {
                fileEntity.setSource("退款详情");
                fileEntity.setReadOnly(1);
                fileEntityList.add(fileEntity);
            });
        }
        return fileEntityList;
    }

    @Override
    public List<CrmModelFiledVO> information(Integer contractId) {
        CrmModel crmModel = queryById(contractId);
        Set<String> set  = crmModel.keySet();
        List<String> keyList = new ArrayList<>(set);

        List<String> systemFieldList = Arrays.asList("checkStatus","refundDate","createUserName","ownerUserId","ownerDeptId", "createTime", "updateTime", "lastTime", "receivedMoney", "unreceivedMoney");

        List<CrmModelFiledVO> crmModelFiledVOS = queryInformation(crmModel, keyList);

        CrmModelFiledVO studentField = crmModelFiledVOS.stream().filter(item -> "studentId".equals(item.getFieldName())).collect(Collectors.toList()).get(0);
        CrmModelFiledVO contractField = crmModelFiledVOS.stream().filter(item -> "contractId".equals(item.getFieldName())).collect(Collectors.toList()).get(0);
        CrmModelFiledVO bankCardAddrField = crmModelFiledVOS.stream().filter(item -> "bankCardAddr".equals(item.getFieldName())).collect(Collectors.toList()).get(0);

        List<String> removeList = Arrays.asList("studentId","contractId","bankCardAddr","ownerDeptId");
        crmModelFiledVOS.removeIf(item -> removeList.contains(item.getFieldName()));
        crmModelFiledVOS.add(new CrmModelFiledVO().setFieldName("checkStatus").setName("审核状态").setValue(crmModel.get("checkStatus")).setFormType("check_status").setFieldType(1));
        LinkedHashMap addressVal = new LinkedHashMap();
        if(ObjectUtil.isNotEmpty(crmModel.get("bankCardAddr"))){
            addressVal = JSON.parseObject((String) crmModel.get("bankCardAddr"), LinkedHashMap.class);
        }
        crmModelFiledVOS.add(bankCardAddrField.getSorting(),new CrmModelFiledVO().setFieldName("map_bankCardAddr").setName("开户行所在省市区").setValue(addressVal).setFormType(FieldEnum.ADDRESS.getFormType()).setFieldType(1).setAuthLevel(3));
        crmModelFiledVOS.add(new CrmModelFiledVO().setFieldName("ownerDeptId").setName("负责人所在部门").setValue(new JSONObject().fluentPut("ownerDeptId", crmModel.get("ownerDeptId")).fluentPut("ownerDeptName", crmModel.get("ownerDeptName"))).setAuthLevel(2).setFieldType(1));
        crmModelFiledVOS.add(contractField.getSorting(),new CrmModelFiledVO().setFieldName("contractId").setName("合同编号").setValue(new JSONObject().fluentPut("contractId", crmModel.get("contractId")).fluentPut("contractNum", crmModel.get("contractNum"))).setFormType("contract").setFieldType(1));
        crmModelFiledVOS.add(studentField.getSorting(),new CrmModelFiledVO().setFieldName("studentId").setName("VIP学员").setValue(new JSONObject().fluentPut("studentId", crmModel.get("studentId")).fluentPut("studentName", crmModel.get("studentName"))).setFormType("student").setFieldType(1));

        return crmModelFiledVOS.stream().sorted(Comparator.comparingInt(r -> -r.getFieldType())).peek(r -> {
            r.setFieldType(null);
            r.setSetting(null);
            r.setType(null);
            r.setAuthLevel(2);

            if (systemFieldList.contains(r.getFieldName())) {
                r.setSysInformation(1);
            } else {
                r.setSysInformation(0);
            }
        }).collect(Collectors.toList());
    }


    @Override
    public void updateInformation(CrmUpdateInformationBO updateInformationBO) {
        String batchId = updateInformationBO.getBatchId();
        Integer refundId = updateInformationBO.getId();
        Integer examineCount = crmExamineService.queryCount(getLabel());
        CrmRefund refund = getById(refundId);
        if (!refund.getCreateUserId().equals(UserUtil.getUserId()) && examineCount > 0) {
            throw new CrmException(CrmCodeEnum.CRM_REFUND_EDIT_ERROR);
        }
        if (refund.getCheckStatus() == 1){
            throw new CrmException(CrmCodeEnum.CRM_REFUND_EXAMINE_PASS_ERROR);
        }
        if (refund.getCheckStatus() != 4 && refund.getCheckStatus() != 2 && refund.getCheckStatus() != 5) {
            throw new CrmException(CrmCodeEnum.CRM_CONTRACT_EDIT_ERROR);
        }
        updateInformationBO.getList().forEach(record -> {
            CrmRefund oldRefund = getById(updateInformationBO.getId());
            Map<String, Object> oldRefundMap = BeanUtil.beanToMap(oldRefund);
            if (record.getInteger("fieldType") == 1) {
                Map<String, Object> crmRefundMap = new HashMap<>(oldRefundMap);
                crmRefundMap.put(record.getString("fieldName"), record.get("value"));
                CrmRefund crmRefund = BeanUtil.mapToBean(crmRefundMap, CrmRefund.class, true);
//                if(StringUtils.isNotBlank(crmRefund.getStudentsCall())){
//                    String telephone = crmRefund.getStudentsCall();
//                    //验证电话格式
//                    if(!(telephone.matches(Const.REG_EXP_MOBILE) || telephone.matches(Const.REG_EXP_TELEPHONE))){
//                        throw new CrmException(CrmCodeEnum.CRM_REG_EXP_ERROR);
//                    }
//                }

                if("teacherId".equals(record.getString("fieldName"))){
                    String teacherName = UserCacheUtil.getUserName(record.getLong("value"));
                    if((!UserUtil.getUserId().equals(oldRefund.getTeacherId())) && (oldRefund.getTeacherId() != null)){
                        addMessage(refund.getNumber(),teacherName,oldRefund.getTeacherId(),AdminMessageEnum.CRM_REFUND_CHANGE_TEACHER_USER.getType(),crmRefund.getRefundId());
                    }

                    if(record.getLong("value") != null){
                        addMessage(oldRefund.getNumber(),teacherName,record.getLong("value"),AdminMessageEnum.CRM_REFUND_CHANGE_TEACHER_USER.getType(),crmRefund.getRefundId());
                    }
                }

                actionRecordUtil.updateRecord(oldRefundMap, crmRefundMap, CrmEnum.REFUND, crmRefund.getNumber(), crmRefund.getRefundId());
                update().set(StrUtil.toUnderlineCase(record.getString("fieldName")), record.get("value")).eq("refund_id",updateInformationBO.getId()).update();
            }
            updateField(record, refundId);
        });
    }

    @Override
    public BasePage<JSONObject> queryListByContractId(BasePage<JSONObject> page, Integer contractId, String conditions) {
        /*BasePage<JSONObject> jsonObjects = getBaseMapper().queryListByContractId(page,contractId, conditions);
        for (JSONObject jsonObject : jsonObjects.getList()) {
            Long ownerUserId = jsonObject.getLong("ownerUserId");
            String ownerUserName = UserCacheUtil.getUserName(ownerUserId);
            jsonObject.put("ownerUserName",ownerUserName);
        }
        return jsonObjects;*/
        return null;
    }

    /**
     * 更新客户下所有合同为未成交状态
     * @param crmContractList
     */
    public void changeContractUnDeal(List<CrmContract> crmContractList){

        for (CrmContract contract : crmContractList) {
            contract.setDealStatus("未成交");
            contract.setDealTime(null);
            contract.setReceivedMoney(new BigDecimal(0));
            contract.setUnreceivedMoney(contract.getMoney());
            SpringUtils.getBean(ICrmContractService.class).updateById(contract);
            // 更新合同ES
            String index = CrmEnum.CONTRACT.getIndex();
            BulkRequest bulkRequest = new BulkRequest();
            UpdateRequest updateRequest = new UpdateRequest(index, "_doc", String.valueOf(contract.getContractId()));
            Map<String, Object> map = new HashMap<>();
            map.put("dealStatus",contract.getDealStatus());
            map.put("dealTime",contract.getDealTime());
            map.put("receivedMoney",contract.getReceivedMoney());
            map.put("unreceivedMoney",contract.getUnreceivedMoney());
            updateRequest.doc(map);
            bulkRequest.add(updateRequest);
            try {
                elasticsearchRestTemplate.getClient().bulk(bulkRequest, RequestOptions.DEFAULT);
                elasticsearchRestTemplate.refresh(index);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 退款记录  更新客户成交状态
     * @param refund
     */
//    @Override
    public void updateCustomerDeal1(CrmRefund refund){

        /** --------------------------学员---------------------------- */
        String index = CrmEnum.CUSTOMER.getIndex();
        CrmCustomer byId = SpringUtils.getBean(ICrmCustomerService.class).getById(refund.getCustomerId());
        byId.setVipDealStatus("已退款");
        byId.setStudentStatus(Const.ALREADY_DROP_OUT);
        crmCustomerService.update(byId,new UpdateWrapper<CrmCustomer>().lambda().set(CrmCustomer::getVipDealTime,null).eq(CrmCustomer::getCustomerId,byId.getCustomerId()));

        BulkRequest customerBulkRequest = new BulkRequest();
        UpdateRequest customerUpdateRequest = new UpdateRequest(index, "_doc", String.valueOf(refund.getCustomerId()));
        Map<String, Object> map = new HashMap<>();
        map.put("vipDealStatus", byId.getVipDealStatus());
        map.put("vipDealTime", null);
        map.put("studentStatus",Const.ALREADY_DROP_OUT);
        customerUpdateRequest.doc(map);
        customerBulkRequest.add(customerUpdateRequest);
        try {
            elasticsearchRestTemplate.getClient().bulk(customerBulkRequest, RequestOptions.DEFAULT);
            elasticsearchRestTemplate.refresh(index);
        } catch (IOException e) {
            e.printStackTrace();
        }

        /** --------------------------VIP学员---------------------------- */
        String studentIndex = CrmEnum.STUDENT.getIndex();
        CrmStudent student = SpringUtils.getBean(ICrmStudentService.class).queryStudentBySerialNumber(byId.getSerialNumber());
        student.setVipDealStatus("已退款");
        student.setStudentStatus(Const.ALREADY_DROP_OUT);
        crmStudentService.update(student,new UpdateWrapper<CrmStudent>().lambda().set(CrmStudent::getVipDealTime,null).eq(CrmStudent::getStudentId,student.getStudentId()));

        BulkRequest vipBulkRequest = new BulkRequest();
        UpdateRequest vipUpdateRequest = new UpdateRequest(studentIndex, "_doc", String.valueOf(student.getStudentId()));
        Map<String, Object> studentMap = new HashMap<>();
        studentMap.put("vipDealStatus", student.getVipDealStatus());
        studentMap.put("vipDealTime", null);
        studentMap.put("studentStatus",Const.ALREADY_DROP_OUT);
        vipUpdateRequest.doc(studentMap);
        vipBulkRequest.add(vipUpdateRequest);
        try {
            elasticsearchRestTemplate.getClient().bulk(vipBulkRequest, RequestOptions.DEFAULT);
            elasticsearchRestTemplate.refresh(studentIndex);
        } catch (IOException e) {
            e.printStackTrace();
        }

        /** --------------------------线索---------------------------- */
        // 更新线索相关信息
        String leadsIndex = CrmEnum.LEADS.getIndex();
        CrmLeads crmLeads = SpringUtils.getBean(ICrmLeadsService.class).queryLeadsDataBySerialNumber(byId.getSerialNumber());
        if(BeanUtil.isNotEmpty(crmLeads)){
            crmLeads.setVipDealStatus("已退款");
            crmLeadsService.update(crmLeads,new UpdateWrapper<CrmLeads>().lambda().set(CrmLeads::getVipDealTime,null).eq(CrmLeads::getLeadsId,crmLeads.getLeadsId()));

            BulkRequest leadsBulkRequest = new BulkRequest();
            UpdateRequest leadsUpdateRequest = new UpdateRequest(leadsIndex, "_doc", String.valueOf(crmLeads.getLeadsId()));
            Map<String, Object> leadsMap = new HashMap<>();
            leadsMap.put("vipDealStatus", student.getVipDealStatus());
            leadsMap.put("vipDealTime", null);
            leadsUpdateRequest.doc(leadsMap);
            leadsBulkRequest.add(leadsUpdateRequest);
            try {
                elasticsearchRestTemplate.getClient().bulk(leadsBulkRequest, RequestOptions.DEFAULT);
                elasticsearchRestTemplate.refresh(leadsIndex);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // 更新合同信息
        // PS：合同金额4000 已回款3000 未回款1000 已退款0
        // PS：退款2000 已回款1000 未回款1000

        QueryWrapper<CrmRefund> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("customer_id", refund.getCustomerId());
        queryWrapper.eq("contract_id", refund.getContractId());
        queryWrapper.and(wrapper -> wrapper.eq("check_status", 1).or().eq("check_status", 3));
        List<CrmRefund> crmRefundList = query().getBaseMapper().selectList(queryWrapper);

        QueryWrapper<CrmReceivables> receivablesQueryWrapper = new QueryWrapper<>();
        receivablesQueryWrapper.eq("customer_id", refund.getCustomerId());
        receivablesQueryWrapper.eq("contract_id", refund.getContractId());
        receivablesQueryWrapper.and(wrapper -> wrapper.eq("check_status", 1).or().eq("check_status", 3));
        List<CrmReceivables> crmReceivablesList = crmReceivablesService.list(receivablesQueryWrapper);

        Map<Integer, List<CrmReceivables>> receivablesMap = crmReceivablesList.stream().collect(Collectors.groupingBy(CrmReceivables::getContractId));

        Map<Integer, List<CrmRefund>> refundMap = crmRefundList.stream().collect(Collectors.groupingBy(CrmRefund::getContractId));

        CrmContract crmContract = crmContractService.getById(refund.getContractId());
        if (crmContract != null && Integer.valueOf(1).equals(crmContract.getCheckStatus())){
            String contractDealStatus = "未成交";

            BigDecimal sum = new BigDecimal(0.00);
            BigDecimal vipSum = new BigDecimal(0.00);
            BigDecimal contractSum = new BigDecimal(0.00);

            List<CrmReceivables> groupList =  receivablesMap.get(crmContract.getContractId());
            if (CollectionUtil.isNotEmpty(groupList)) {
                for (CrmReceivables crmReceivables : groupList) {
                    if (ObjectUtil.isNotEmpty(crmReceivables.getMoney())) {
                        sum = sum.add(crmReceivables.getMoney());
                        contractSum = contractSum.add(crmReceivables.getMoney());
                        if(crmReceivables.getCheckStatus() == 1){
                            vipSum = vipSum.add(crmReceivables.getMoney());
                        }
                    }
                }
                log.info("第二级：回款vipSum"+vipSum);
            }

            BigDecimal refundMoney = new BigDecimal(0.00);

            List<CrmRefund> refundGroupList = refundMap.get(crmContract.getContractId());
            if (CollectionUtil.isNotEmpty(refundGroupList)) {
                for (CrmRefund crmRefund : refundGroupList) {
                    if (ObjectUtil.isNotEmpty(crmRefund.getMoney())) {
                        sum = sum.subtract(crmRefund.getMoney());
                        contractSum = contractSum.subtract(crmRefund.getMoney());
                        if(crmRefund.getCheckStatus() == 1){
                            vipSum = vipSum.subtract(crmRefund.getMoney());
                            refundMoney = refundMoney.add(crmRefund.getMoney());
                        }
                    }
                }
                log.info("第二级：回款vipSum"+vipSum);
            }

            if(sum.doubleValue() > 0){
                contractDealStatus = "已成交";
            }

            crmContract.setReceivedMoney(contractSum);
//            crmContract.setUnreceivedMoney(crmContract.getMoney().subtract(contractSum));
            crmContract.setRefundMonery(refundMoney);
            if(vipSum.doubleValue() == crmContract.getMoney().doubleValue()){
                crmContract.setBackStatus("已回款");
            }else if(vipSum.doubleValue() < crmContract.getMoney().doubleValue() && vipSum.doubleValue() > 0){
                crmContract.setBackStatus("回款中");
            }else{
                crmContract.setBackStatus("未回款");
            }
            updateContractDealStatus(crmContract,contractDealStatus);
        }
    }

    @Override
    public void updateCustomerDeal(CrmRefund refund){
        QueryWrapper<CrmRefund> refundQueryWrapper = new QueryWrapper<>();
        refundQueryWrapper.eq("customer_id",refund.getCustomerId());
        refundQueryWrapper.and(wrapper -> wrapper.eq("check_status", 1).or().eq("check_status", 3));
        List<CrmRefund> refundList = list(refundQueryWrapper);

        QueryWrapper<CrmReceivables> receivablesQueryWrapper = new QueryWrapper<>();
        receivablesQueryWrapper.eq("customer_id", refund.getCustomerId());
        receivablesQueryWrapper.and(wrapper -> wrapper.eq("check_status", 1).or().eq("check_status", 3));
        List<CrmReceivables> receivablesList = crmReceivablesService.getBaseMapper().selectList(receivablesQueryWrapper);

        Map<Integer, List<CrmRefund>> refundMap = refundList.stream().collect(Collectors.groupingBy(CrmRefund::getContractId));
        Map<Integer, List<CrmReceivables>> receivablesMap = receivablesList.stream().collect(Collectors.groupingBy(CrmReceivables::getContractId));

        String vipStudentDealStatus = "未成交";

        CrmContract crmContract = crmContractService.getById(refund.getContractId());

        if(CrmBusinessConstEnum.账单类别_首付款合同.getMsg().equals(crmContract.getContractCategory())){
            List<CrmReceivables> groupList =  receivablesMap.get(crmContract.getContractId());

            BigDecimal contractSum = new BigDecimal(0.00);
            String contractDealStatus = "未成交";

            for (CrmReceivables crmReceivables : groupList) {
                if (ObjectUtil.isNotEmpty(crmReceivables.getMoney())) {
                    contractSum = contractSum.add(crmReceivables.getMoney());
                }
            }

            if(contractSum.doubleValue() > 0){
                contractDealStatus = "已成交";
            }

            // 更新合同信息（是否成交，已回款金额，未回款金额）
            crmContract.setReceivedMoney(contractSum);
            crmContract.setUnreceivedMoney(crmContract.getMoney().subtract(contractSum));

            BigDecimal refundMoney = new BigDecimal(0.00);
            List<CrmRefund> refundGroupList = refundMap.get(crmContract.getContractId());
            if (CollectionUtil.isNotEmpty(refundGroupList)) {
                for (CrmRefund crmRefund : refundGroupList) {
                    if (ObjectUtil.isNotEmpty(crmRefund.getMoney())) {
                        contractSum = contractSum.subtract(crmRefund.getMoney());
                        if(crmRefund.getCheckStatus() == 1){
                            refundMoney = refundMoney.add(crmRefund.getMoney());
                        }
                    }
                }
            }

            crmContract.setReceivedMoney(contractSum);
            crmContract.setRefundMonery(refundMoney);
            if(refundMoney.doubleValue() > 0){
                crmContract.setRepaymentStatus(CrmRepaidStatusEnum.已退学.getRemarks());
                crmContract.setStudentStatus(CrmBusinessConstEnum.入学状态_已退学.getMsg());
            }else if(contractSum.doubleValue() == crmContract.getMoney().doubleValue()){
                crmContract.setRepaymentStatus(CrmRepaidStatusEnum.已还清.getRemarks());
            }else if(contractSum.doubleValue() < crmContract.getMoney().doubleValue() && contractSum.doubleValue() > 0){
                crmContract.setRepaymentStatus(CrmRepaidStatusEnum.还款中.getRemarks());
            }
            updateContractDealStatus(crmContract,contractDealStatus);

            updateReceivablesStudentStatus(crmContract.getContractId(), crmContract.getRepaymentStatus());

            return;
        }

        BigDecimal sum = new BigDecimal(0.00);
        BigDecimal vipSum = new BigDecimal(0.00);
        BigDecimal contractSum = new BigDecimal(0.00);
        BigDecimal refundMoney = new BigDecimal(0.00);

        String repaymentStatus = CrmRepaidStatusEnum.还款中.getRemarks();

        if (crmContract != null && Integer.valueOf(1).equals(crmContract.getCheckStatus())){
            String contractDealStatus = "未成交";

            List<CrmReceivables> groupList =  receivablesMap.get(crmContract.getContractId());
            if (CollectionUtil.isNotEmpty(groupList)) {
                for (CrmReceivables crmReceivables : groupList) {
                    if (ObjectUtil.isNotEmpty(crmReceivables.getMoney())) {
                        sum = sum.add(crmReceivables.getMoney());
                        contractSum = contractSum.add(crmReceivables.getMoney());
                        if(crmReceivables.getCheckStatus() == 1){
                            vipSum = vipSum.add(crmReceivables.getMoney());
                        }
                    }
                }
                log.info("第二级：回款vipSum"+vipSum);
            }

            List<CrmRefund> refundGroupList = refundMap.get(crmContract.getContractId());
            if (CollectionUtil.isNotEmpty(refundGroupList)) {
                for (CrmRefund crmRefund : refundGroupList) {
                    if (ObjectUtil.isNotEmpty(crmRefund.getMoney())) {
                        sum = sum.subtract(crmRefund.getMoney());
                        if(crmRefund.getCheckStatus() == 1){
                            refundMoney = refundMoney.add(crmRefund.getMoney());
                        }
                    }
                }
                log.info("第二级：回款vipSum"+vipSum);
            }

            if(contractSum.doubleValue() > 0){
                contractDealStatus = "已成交";
            }
            if(vipSum.doubleValue() > 0){
                vipStudentDealStatus = "已成交";
            }

            crmContract.setReceivedMoney(contractSum);
            crmContract.setRefundMonery(refundMoney);
            if(refundMoney.doubleValue() > 0){
                repaymentStatus = CrmRepaidStatusEnum.已退学.getRemarks();
                crmContract.setStudentStatus(CrmBusinessConstEnum.入学状态_已退学.getMsg());
                crmContract.setRepaymentStatus(CrmRepaidStatusEnum.已退学.getRemarks());
            }else if(vipSum.doubleValue() >= crmContract.getMoney().doubleValue()){
                repaymentStatus = CrmRepaidStatusEnum.已还清.getRemarks();
                crmContract.setRepaymentStatus(CrmRepaidStatusEnum.已还清.getRemarks());
            }else{
                repaymentStatus = CrmRepaidStatusEnum.还款中.getRemarks();
                crmContract.setRepaymentStatus(CrmRepaidStatusEnum.还款中.getRemarks());
            }
            updateContractDealStatus(crmContract,contractDealStatus);

            updateReceivablesStudentStatus(crmContract.getContractId(), crmContract.getStudentStatus());
        }


        /** --------------------------学员---------------------------- */
        String index = CrmEnum.CUSTOMER.getIndex();
        CrmCustomer byId = SpringUtils.getBean(ICrmCustomerService.class).getById(refund.getCustomerId());
        byId.setVipDealStatus(vipStudentDealStatus);
        byId.setStudentStatus(refundMoney.doubleValue() > 0 ? Const.ALREADY_DROP_OUT : Const.ALREADY_ENTRANCE);
        byId.setRepaymentStatus(repaymentStatus);
        crmCustomerService.update(byId,new UpdateWrapper<CrmCustomer>().lambda().eq(CrmCustomer::getCustomerId,byId.getCustomerId()));

        BulkRequest customerBulkRequest = new BulkRequest();
        UpdateRequest customerUpdateRequest = new UpdateRequest(index, "_doc", String.valueOf(refund.getCustomerId()));
        Map<String, Object> map = new HashMap<>();
        map.put("vipDealStatus", byId.getVipDealStatus());
        map.put("studentStatus",refundMoney.doubleValue() > 0 ? Const.ALREADY_DROP_OUT : Const.ALREADY_ENTRANCE);
        map.put("repaymentStatus",repaymentStatus);
        customerUpdateRequest.doc(map);
        customerBulkRequest.add(customerUpdateRequest);
        try {
            elasticsearchRestTemplate.getClient().bulk(customerBulkRequest, RequestOptions.DEFAULT);
            elasticsearchRestTemplate.refresh(index);
        } catch (IOException e) {
            e.printStackTrace();
        }

        /** --------------------------VIP学员---------------------------- */
        String studentIndex = CrmEnum.STUDENT.getIndex();
        CrmStudent student = SpringUtils.getBean(ICrmStudentService.class).queryStudentBySerialNumber(byId.getSerialNumber());
        student.setVipDealStatus(vipStudentDealStatus);
        student.setStudentStatus(refundMoney.doubleValue() > 0 ? Const.ALREADY_DROP_OUT : Const.ALREADY_ENTRANCE);
        student.setRepaymentStatus(repaymentStatus);
        crmStudentService.update(student,new UpdateWrapper<CrmStudent>().lambda().eq(CrmStudent::getStudentId,student.getStudentId()));

        BulkRequest vipBulkRequest = new BulkRequest();
        UpdateRequest vipUpdateRequest = new UpdateRequest(studentIndex, "_doc", String.valueOf(student.getStudentId()));
        Map<String, Object> studentMap = new HashMap<>();
        studentMap.put("vipDealStatus", student.getVipDealStatus());
        studentMap.put("studentStatus",refundMoney.doubleValue() > 0 ? Const.ALREADY_DROP_OUT : Const.ALREADY_ENTRANCE);
        studentMap.put("repaymentStatus",repaymentStatus);
        vipUpdateRequest.doc(studentMap);
        vipBulkRequest.add(vipUpdateRequest);
        try {
            elasticsearchRestTemplate.getClient().bulk(vipBulkRequest, RequestOptions.DEFAULT);
            elasticsearchRestTemplate.refresh(studentIndex);
        } catch (IOException e) {
            e.printStackTrace();
        }

        /** --------------------------线索---------------------------- */
        // 更新线索相关信息
        String leadsIndex = CrmEnum.LEADS.getIndex();
        CrmLeads crmLeads = SpringUtils.getBean(ICrmLeadsService.class).queryLeadsDataBySerialNumber(byId.getSerialNumber());
        if(BeanUtil.isNotEmpty(crmLeads)){
            crmLeads.setVipDealStatus(vipStudentDealStatus);
            crmLeadsService.update(crmLeads,new UpdateWrapper<CrmLeads>().lambda().eq(CrmLeads::getLeadsId,crmLeads.getLeadsId()));

            BulkRequest leadsBulkRequest = new BulkRequest();
            UpdateRequest leadsUpdateRequest = new UpdateRequest(leadsIndex, "_doc", String.valueOf(crmLeads.getLeadsId()));
            Map<String, Object> leadsMap = new HashMap<>();
            leadsMap.put("vipDealStatus", student.getVipDealStatus());
            leadsUpdateRequest.doc(leadsMap);
            leadsBulkRequest.add(leadsUpdateRequest);
            try {
                elasticsearchRestTemplate.getClient().bulk(leadsBulkRequest, RequestOptions.DEFAULT);
                elasticsearchRestTemplate.refresh(leadsIndex);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if(refundMoney.doubleValue() > 0){
            if(student.getAssistantUserId() != null){
                // 退款审批通过退学新增消息
                addMessage(student.getCustomerName(),refund.getNumber(),student.getAssistantUserId(),AdminMessageEnum.CRM_REFUND_CHECK_OK_DROPOUT.getType(),student.getStudentId());
            }
        }

    }

    /**
     * 更新合同 成交状态
     * @param contract
     * @param dealStatus
     */
    public void updateContractDealStatus(CrmContract contract, String dealStatus){

        String index = CrmEnum.CONTRACT.getIndex();
        String oldDealStatus = contract.getDealStatus();
        if(!dealStatus.equals(oldDealStatus)){
            contract.setDealStatus(dealStatus);
            if("已成交".equals(dealStatus)){
                contract.setDealTime(new Date());
            }else{
                contract.setDealTime(null);
            }
            SpringUtils.getBean(ICrmContractService.class).updateById(contract);
            BulkRequest bulkRequest = new BulkRequest();
            UpdateRequest updateRequest = new UpdateRequest(index, "_doc", String.valueOf(contract.getContractId()));
            Map<String, Object> map = new HashMap<>();
            map.put("dealStatus", dealStatus);
            if("已成交".equals(dealStatus)){
                map.put("dealTime", DateUtil.formatDateTime(new Date()));
            }else{
                map.put("dealTime", null);
            }
            map.put("repaymentStatus",contract.getRepaymentStatus());
            map.put("studentStatus",contract.getStudentStatus());
            map.put("receivedMoney",contract.getReceivedMoney());
            map.put("backStatus",contract.getBackStatus());
//            map.put("unreceivedMoney",contract.getUnreceivedMoney());
            map.put("refundMonery",contract.getRefundMonery());
            updateRequest.doc(map);
            bulkRequest.add(updateRequest);
            try {
                elasticsearchRestTemplate.getClient().bulk(bulkRequest, RequestOptions.DEFAULT);
                elasticsearchRestTemplate.refresh(index);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else{
            //更新合同金额
            SpringUtils.getBean(ICrmContractService.class).updateById(contract);
            BulkRequest bulkRequest = new BulkRequest();
            UpdateRequest updateRequest = new UpdateRequest(index, "_doc", String.valueOf(contract.getContractId()));
            Map<String, Object> map = new HashMap<>();
            map.put("receivedMoney",contract.getReceivedMoney());
//            map.put("unreceivedMoney",contract.getUnreceivedMoney());
            map.put("refundMonery",contract.getRefundMonery());
            map.put("backStatus",contract.getBackStatus());
            map.put("repaymentStatus",contract.getRepaymentStatus());
            map.put("studentStatus",contract.getStudentStatus());
            updateRequest.doc(map);
            bulkRequest.add(updateRequest);
            try {
                elasticsearchRestTemplate.getClient().bulk(bulkRequest, RequestOptions.DEFAULT);
                elasticsearchRestTemplate.refresh(index);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void updateReceivablesStudentStatus(Integer contractId,String studentStatus){
        QueryWrapper<CrmReceivables> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("contract_id", contractId);
        queryWrapper.ne("check_status", 7);
        List<CrmReceivables> receivablesList = crmReceivablesService.getBaseMapper().selectList(queryWrapper);

        List<Integer> receivablesIds = receivablesList.stream().map(CrmReceivables::getReceivablesId).collect(Collectors.toList());

        LambdaUpdateWrapper<CrmReceivables> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(CrmReceivables::getStudentStatus, studentStatus);
        updateWrapper.in(CrmReceivables::getReceivablesId, receivablesIds);
        crmReceivablesService.update(updateWrapper);

        ElasticUtil.updateField(elasticsearchRestTemplate,"studentStatus",studentStatus,receivablesIds, CrmEnum.RECEIVABLES.getIndex());

    }

    public List<Map<String,Object>> queryPutinStatis(List<Integer> customerIds,List<Long> userIdList){
        return baseMapper.queryPutinStatis(customerIds,userIdList);
    }

    public BigDecimal queryRefundMoneyByData(CrmRoiPutinPageBO crmRoiPutinPageBO){
        return baseMapper.queryRefundMoneyByData(crmRoiPutinPageBO);
    }

}
